-- ********************************************
-- * Copyright (c) 2012 TPV R&D Center Brazil *
-- * All Rights Reserved                      *
-- ********************************************

--- toolkit.component.Window

local Window = Box:new()

function Window:new(o)
   if (type(o) ~= 'table') then
      o = {}
   end

   local newWindow = Box:new(o)

   newWindow.parent = nil

   --generate canvas object
   newWindow.content = canvas:new(newWindow.area.width, newWindow.area.height)

   newWindow.layers = {}

   --generate window object
   setmetatable(newWindow, self)
   self.__index = self

   return newWindow
end

function Window:compose(box)
   if (box.componentType == "Box") then

      local nLeft = self.area.left
      local nTop = self.area.top

      --reset window position
      self:setArea({
         left = 0,
         top = 0
      })

      box:updateArea()

      for i = 1, #box.children do

         box.children[i].parent = self

         --check if layer exists
         if (not self.layers[box.children[i].z]) then
            self.layers[box.children[i].z] = {}
            self.layers[box.children[i].z].content = canvas:new(self.area.width, self.area.height)
            self.layers[box.children[i].z].content:attrColor(0, 0, 0, 0)
            self.layers[box.children[i].z].content:clear()
            self.layers[box.children[i].z].left = 0
            self.layers[box.children[i].z].top = 0
         end

         if (box.children[i].visible) then
            if (box.children[i].componentType == "Label") then
               self:composeLabel(box.children[i])
            elseif (box.children[i].componentType == "Rectangle") then
               self:composeRect(box.children[i])
            elseif (box.children[i].componentType == "Circle") then
               self:composeCircle(box.children[i])
            elseif (box.children[i].componentType == "Image") then
               self:composeImage(box.children[i])
            elseif (box.children[i].componentType == "List") then
               self:composeList(box.children[i])
            elseif (box.children[i].componentType == "ListBase") then
               self:composeListBase(box.children[i])
            elseif (box.children[i].componentType == "ListHUB") then
               self:composeListHUB(box.children[i])
            elseif (box.children[i].componentType == "ListEPG") then
               self:composeListEPG(box.children[i])
            elseif (box.children[i].componentType == "ProgressBar") then
               self:composeProgressBar(box.children[i])
            elseif (box.children[i].componentType == "SignalMeter") then
               self:composeSignalMeter(box.children[i])
            elseif (box.children[i].componentType == "IndexPage") then
               self:composeIndexPage(box.children[i])
            elseif (box.children[i].componentType == "TextBox") then
               self:composeTextBox(box.children[i])
            end
         end
      end

      --clear
      self.content:attrColor(unpack(self.color))
      self.content:clear()

      for i,v in pairs(self.layers) do
         self.content:compose(v.left, v.top, v.content)
      end

      --restore window position
      self:setArea({
         left = nLeft,
         top = nTop
      })
   end
end

function Window:composeLabel(label, state, content)
   if (content == nil) then
      content = self.layers[label.z].content
   end

   local tFormat = {}

   --set label state
   if(state == 'deactivated') then
      tFormat = label.deactivated
   elseif(state == 'focused') then
      tFormat = label.focused
   elseif(state == 'selected') then
      tFormat = label.selected
   else
      tFormat = label.activated
   end

   --update area
--   label:updateArea()

   --set font
   content:attrFont(tFormat.type, tFormat.size, tFormat.style)

   local tTextBox = {''}
   local sSpace = ' '

   if (label.area.width > 0) and (label.area.height > 0) then
      --adjust text inside area
      for sBlock in label.text:gmatch("[^\ ]+") do
         if (content:measureText(tTextBox[#tTextBox] .. sBlock) < label.area.width) then
            tTextBox[#tTextBox] = tTextBox[#tTextBox] .. sSpace .. sBlock
         else
            tTextBox[#tTextBox + 1] = ''
            tTextBox[#tTextBox] = tTextBox[#tTextBox] .. sSpace .. sBlock
         end
      end
      label.textLines = #tTextBox
   else
      local nWidth, nHeight = content:measureText(label.text)

      nWidth = nWidth + 2

      if (label.area.width < 1) then
         label.area.width = nWidth
      end

      if (label.area.height < 1) then
         label.area.height = nHeight
      end

      --keep text unchanged
      tTextBox[1] = label.text
   end

   --update area
   label:updateArea()

   local nPosLeft = label.area.left
   local nPosTop = label.area.top

   local clipX, clipY, clipW, clipH = content:attrClip()
   local nR, nG, nB, nA = content:attrColor()

   --clip area
   content:attrClip(nPosLeft, nPosTop, label.area.width, label.area.height)

   --draw background
   if (label.color[4] > 0) then
      content:attrColor(unpack(label.color))
      content:drawRect('fill', label.area.left, label.area.top, label.area.width, label.area.height)
   end

   --align and draw text
   for i = 1, #tTextBox do
      local nAlign = 0
      local nLeft = 0
      local nTop  = 0

      --remove blank space in first position
      if(string.sub(tTextBox[i], 1, 1) == sSpace) then
         tTextBox[i] = string.sub(tTextBox[i], 2, #tTextBox[i])
      end

      --check align
      if (label.align == 'LEFT') then
         nAlign = 0
      elseif (label.align == 'CENTER') then
         nAlign = math.floor((label.area.width / 2)) - math.ceil((content:measureText(tTextBox[i]) / 2))
      elseif (label.align == 'RIGHT') then
         nAlign = label.area.width - content:measureText(tTextBox[i])
      end

      --update left and top positions
      nLeft = nPosLeft + nAlign
      nTop  = nPosTop + (label.spacing * (i - 1))

      --draw shadow
      if (label.shadow.shift > 0) then
         content:attrColor(unpack(label.shadow.color))
         content:drawText(nLeft + label.shadow.shift, nTop + label.shadow.shift, tTextBox[i])
      end

      --draw text
      content:attrColor(unpack(tFormat.color))
      content:drawText(nLeft, nTop, tTextBox[i])
   end

   --unclip area
   content:attrClip(clipX, clipY, clipW, clipH)
   content:attrColor(nR, nG, nB, nA)

   --update anchors
   label.left[1] = label.area.left
   label.top[1] = label.area.top
   label.right[1] = label.area.left + label.area.width
   label.bottom[1] = label.area.top + label.area.height
end

function Window:composeRect(rect, content)
   if (content == nil) then
      content = self.layers[rect.z].content
   end

   --update area
   rect:updateArea()

   local nPosLeft = rect.area.left
   local nPosTop = rect.area.top

   local clipX, clipY, clipW, clipH = content:attrClip()
   local nR, nG, nB, nA = content:attrColor()

   --clip border area
  	content:attrClip(nPosLeft, nPosTop, rect.area.width, rect.area.height)

   --draw border
   if ((rect.borderColor ~= nil) and (rect.borderColor[4] > 0)) then
      content:attrColor(unpack(rect.borderColor))
      content:drawRect('fill', rect.area.left, rect.area.top, rect.area.width, rect.area.height)
   else
      rect.borderWidth = 0
   end

   --clip area
   content:attrClip(nPosLeft + rect.borderWidth, nPosTop + rect.borderWidth, rect.area.width - (rect.borderWidth * 2), rect.area.height - (rect.borderWidth * 2))
   content:attrColor(0, 0, 0, 0)
   content:clear()

   --draw background
   if (rect.color[4] > 0) then
      content:attrColor(unpack(rect.color))
      content:drawRect('fill', rect.area.left + rect.borderWidth, rect.area.top + rect.borderWidth, rect.area.width - (rect.borderWidth * 2), rect.area.height - (rect.borderWidth * 2))
   end

   --unclip area
   content:attrClip(clipX, clipY, clipW, clipH)
   content:attrColor(nR, nG, nB, nA)

   --update anchors
   rect.left[1] = rect.area.left
   rect.top[1] = rect.area.top
   rect.right[1] = rect.area.left + rect.area.width
   rect.bottom[1] = rect.area.top + rect.area.height
end

function Window:composeCircle(circle, content)
   if (content == nil) then
      content = self.layers[circle.z].content
   end

   circle.area.width = circle.radius * 2
   circle.area.height = circle.radius * 2

   --update area
   circle:updateArea()

   local nPosLeft = circle.area.left
   local nPosTop = circle.area.top

   local clipX, clipY, clipW, clipH = content:attrClip()
   local nR, nG, nB, nA = content:attrColor()

   --clip area
  	content:attrClip(nPosLeft, nPosTop, circle.area.width, circle.area.height)
  	--content:attrClip(0, 0, 1280, 720)

   --draw background
   if (circle.color[4] > 0) then
      content:attrColor(unpack(circle.color))
      content:drawEllipse('fill', nPosLeft + circle.radius, nPosTop + circle.radius, circle.radius, circle.radius, circle.angle, 360)
   end

   --unclip area
   content:attrClip(clipX, clipY, clipW, clipH)
   content:attrColor(nR, nG, nB, nA)

   --update anchors
   circle.left[1] = circle.area.left
   circle.top[1] = circle.area.top
   circle.right[1] = circle.area.left + circle.area.width
   circle.bottom[1] = circle.area.top + circle.area.height
end

function Window:composeImage(image, state, content)
   if (content == nil) then
      content = self.layers[image.z].content
   end

   local tFormat = {}

   --set image state
   if (state == 'deactivated') then
      tFormat = image.deactivated
   elseif (state == 'focused') then
      tFormat = image.focused
   elseif (state == 'selected') then
      tFormat = image.selected
   else
      tFormat = image.activated
   end

   local imageContent = canvas:new(image.fileName)

   --check image size
   local nWidth, nHeight = imageContent:attrSize()

   if (image.area.width <= 0) then
      image.area.width = nWidth
   end

   if (image.area.height <= 0) then
      image.area.height = nHeight
   end

   --update area
   image:updateArea()

   --check anchors
   if (image.anchors.fill) then
      tFormat.resizeWidth = image.area.width
      tFormat.resizeHeight = image.area.height
   elseif (image.anchors.left and image.anchors.right) then
      tFormat.resizeWidth = image.area.width
   elseif (image.anchors.top and image.anchors.bottom) then
      tFormat.resizeHeight = image.area.height
   end

   --resize image
   if (tFormat.resizeWidth > 0 or tFormat.resizeHeight > 0) then

      if (tFormat.resizeWidth > 0) then
         nWidth = tFormat.resizeWidth
         image.area.width = nWidth
      else
         nWidth = image.area.width
      end

      if (tFormat.resizeHeight > 0) then
         nHeight = tFormat.resizeHeight
         image.area.height = nHeight
      else
         nHeight = image.area.height
      end

      imageContent:attrScale(nWidth, nHeight)
   end

   --flip image
   if (tFormat.flipHorizontally or tFormat.flipVertically) then
      imageContent:attrFlip(tFormat.flipHorizontally, tFormat.flipVertically)
   end

   --rotate image
   if (tFormat.rotation > 0) then

      imageContent:attrRotation(tFormat.rotation)

      if (tFormat.rotation == 90 or tFormat.rotation == 270) then
         local nShift = nWidth
         nWidth = nHeight
         nHeight = nShift
      end
   end

   --set opacity
   if (tFormat.opacity < 255) then
      imageContent:attrOpacity(tFormat.opacity)
   end

   local clipX, clipY, clipW, clipH = content:attrClip()
   local nR, nG, nB, nA = content:attrColor()

   --clip area
   content:attrClip(image.area.left, image.area.top, nWidth, nHeight)

   --draw background
   if (image.color[4] > 0) then
      content:attrColor(unpack(image.color))
      content:drawRect('fill', image.area.left, image.area.top, nWidth, nHeight)
   end

   --compose image
   content:compose(image.area.left, image.area.top, imageContent)

   --unclip area
   content:attrClip(clipX, clipY, clipW, clipH)
   content:attrColor(nR, nG, nB, nA)

   imageContent = nil
   collectgarbage()

   --update anchors
   image.left[1] = image.area.left
   image.top[1] = image.area.top
   image.right[1] = image.area.left + image.area.width
   image.bottom[1] = image.area.top + image.area.height
end

function Window:composeList(list, state, content)
   if (content == nil) then
      content = self.layers[list.z].content
   end

   if (#list.nav.columnLimit < 1) then
      print("##### [GUILT] WARNING composeList: list data not loaded!!!")
      return
   end

   --update area
   list:updateArea()

   --set line page position and size
   list.page.linePosition = 1
   list.page.intervalTop = math.floor(list.area.height / list.page.lineSize)

   if (list.page.lineSize > list.nav.lineLimit) then
      list.page.lineSize = list.nav.lineLimit
   end

   --set column page position and size
   if (list.page.hideScroll) then
      list.page.intervalLeft = list.area.width / list.page.columnSize
   else
      list.page.intervalLeft = (list.area.width - list.scroll.width) / list.page.columnSize
   end

   --update line position
   if (list.nav.curLine > list.page.lineSize) then
      list.page.linePosition = list.nav.curLine - list.page.lineSize + 1
   end

   --update column position
   if (list.nav.curColumn > list.page.columnSize) then
      list.page.columnPosition[list.nav.curLine] = list.nav.curColumn - list.page.columnSize + 1
   end
   --compose focus content
   self:composeFocusContent(list)

   --compose scroll content
   self:composeScrollContent(list)

   --compose list content
   self:composeListContent(list)

   local clipX, clipY, clipW, clipH = content:attrClip()
   local nR, nG, nB, nA = content:attrColor()

   --clip area
   content:attrClip(list.area.left, list.area.top, list.area.width, list.area.height)

   --draw background
   if (list.color[4] > 0) then
      content:attrColor(unpack(list.color))
      content:drawRect('fill', list.area.left, list.area.top, list.area.width, list.area.height)
   end

   if (list.isFocusFront) then
      local nLeft = list.area.left
      local nTop = list.area.top

      content:attrClip(list.area.left, list.area.top, list.page.columnSize * list.page.intervalLeft, list.page.lineSize * list.page.intervalTop)
      content:compose(nLeft, nTop, list.listContent)

      nLeft = list.area.left + ((list.nav.curColumn - list.page.columnPosition[list.nav.curLine]) * list.page.intervalLeft)
      nTop = list.area.top + ((list.nav.curLine - list.page.linePosition) * list.page.intervalTop)

      content:attrClip(nLeft, nTop, list.page.intervalLeft, list.page.intervalTop)
      content:compose(nLeft, nTop, list.focusContent)
   else
      local nLeft = list.area.left + ((list.nav.curColumn - list.page.columnPosition[list.nav.curLine]) * list.page.intervalLeft)
      local nTop = list.area.top + ((list.nav.curLine - list.page.linePosition) * list.page.intervalTop)

      content:attrClip(nLeft, nTop, list.page.intervalLeft, list.page.intervalTop)
      content:compose(nLeft, nTop, list.focusContent)

      nLeft = list.area.left
      nTop = list.area.top

      content:attrClip(list.area.left, list.area.top, list.page.columnSize * list.page.intervalLeft, list.page.lineSize * list.page.intervalTop)
      content:compose(nLeft, nTop, list.listContent)
   end

   nLeft = list.area.left
   nTop = list.area.top

   --check scroll
   if (list.scrollContent) then
      nLeft = list.area.left + list.area.width - list.scroll.width
      nTop = list.area.top + math.floor((list.page.linePosition - 1) * (list.area.height / list.nav.lineLimit))

      local nWidth, nHeight = list.scrollContent:attrSize()

      --clip area
      content:attrClip(nLeft, nTop, nWidth, nHeight)
      --compose scroll
      content:compose(nLeft, nTop, list.scrollContent)
   end

   --unclip area
   content:attrClip(clipX, clipY, clipW, clipH)
   content:attrColor(nR, nG, nB, nA)
end

function Window:composeListBase(list, state, content)
   if (content == nil) then
      content = self.layers[list.z].content
   end

   --update area
   list:updateArea()

   --set line page position and size
   list.page.linePosition = 1
   list.page.intervalTop = math.floor(list.area.height / list.page.lineSize)

   if (list.page.lineSize > list.nav.lineLimit) then
      list.page.lineSize = list.nav.lineLimit
   end

   --set column page position and size
   if (list.page.hideScroll) then
      list.page.intervalLeft = list.area.width / list.page.columnSize
   else
      list.page.intervalLeft = (list.area.width - list.scroll.width) / list.page.columnSize
   end

   --update line position
   if (list.nav.curLine > list.page.lineSize) then
      list.page.linePosition = list.nav.curLine - list.page.lineSize + 1
   end

   --update column position
   if (list.nav.curColumn > list.page.columnSize) then
      list.page.columnPosition[list.nav.curLine] = list.nav.curColumn - list.page.columnSize + 1
   end
   --compose focus content
   self:composeFocusContentBase(list)

   --compose scroll content
   self:composeScrollContentBase(list)

   --compose list content
   self:composeListContentBase(list)

   local clipX, clipY, clipW, clipH = content:attrClip()
   local nR, nG, nB, nA = content:attrColor()

   --clip area
   content:attrClip(list.area.left, list.area.top, list.area.width, list.area.height)

   local nLeft = list.area.left + ((list.nav.curColumn - list.page.columnPosition) * list.page.intervalLeft)
   local nTop = list.area.top + ((list.nav.curLine - list.page.linePosition) * list.page.intervalTop)

   content:attrClip(nLeft, nTop, list.page.intervalLeft, list.page.intervalTop)
   content:compose(nLeft, nTop, list.focusContent)

   nLeft = list.area.left
   nTop = list.area.top

   content:attrClip(list.area.left, list.area.top, list.page.columnSize * list.page.intervalLeft, list.page.lineSize * list.page.intervalTop)
   content:compose(nLeft, nTop, list.listContent)

   nLeft = list.area.left
   nTop = list.area.top

   --check scroll
   if (list.scrollContent and not list.page.hideScroll) then
      nLeft = list.area.left + list.area.width - list.scroll.width
      nTop = list.area.top + math.floor((list.page.linePosition - 1) * (list.area.height / list.nav.lineLimit))

      local nWidth, nHeight = list.scrollContent:attrSize()

      --clip area
      content:attrClip(nLeft, nTop, nWidth, nHeight)
      --compose scroll
      content:compose(nLeft, nTop, list.scrollContent)
   end

   --unclip area
   content:attrClip(clipX, clipY, clipW, clipH)
   content:attrColor(nR, nG, nB, nA)
end

function Window:composeListHUB(list, state, content)
   if (content == nil) then
      content = self.layers[list.z].content
   end

   --update area
   list:updateArea()

   --set line page position and size
   list.page.linePosition = 1
   list.page.intervalTop = math.floor(list.area.height / list.page.lineSize)

   if (list.page.lineSize > list.nav.lineLimit) then
      list.page.lineSize = list.nav.lineLimit
   end

   --set column page position and size
   if (list.page.hideScroll) then
      list.page.intervalLeft = list.area.width / list.page.columnSize
   else
      list.page.intervalLeft = (list.area.width - list.scroll.width) / list.page.columnSize
   end

   --update line position
   if (list.nav.curLine > list.page.lineSize) then
      list.page.linePosition = list.nav.curLine - list.page.lineSize + 1
   end

   --update column position
   if (list.nav.curColumn > list.page.columnSize) then
      list.page.columnPosition[list.nav.curLine] = list.nav.curColumn - list.page.columnSize + 1
   end
   --compose focus content
   self:composeFocusContentHUB(list)

   --compose scroll content
   self:composeScrollContentHUB(list)

   --compose list content
   self:composeListContentHUB(list)

   local clipX, clipY, clipW, clipH = content:attrClip()
   local nR, nG, nB, nA = content:attrColor()

   --clip area
   content:attrClip(list.area.left, list.area.top, list.area.width, list.area.height)

   local nLeft = list.area.left + ((list.nav.curColumn - list.page.columnPosition) * list.page.intervalLeft)
   local nTop = list.area.top + ((list.nav.curLine - list.page.linePosition) * list.page.intervalTop)

   content:attrClip(nLeft, nTop, list.page.intervalLeft, list.page.intervalTop)
   content:compose(nLeft, nTop, list.focusContent)

   nLeft = list.area.left
   nTop = list.area.top

   content:attrClip(list.area.left, list.area.top, list.page.columnSize * list.page.intervalLeft, list.page.lineSize * list.page.intervalTop)
   content:compose(nLeft, nTop, list.listContent)

   nLeft = list.area.left
   nTop = list.area.top

   --check scroll
   if (list.scrollContent and not list.page.hideScroll) then
      nLeft = list.area.left + list.area.width - list.scroll.width
      nTop = list.area.top + math.floor((list.page.linePosition - 1) * (list.area.height / list.nav.lineLimit))

      local nWidth, nHeight = list.scrollContent:attrSize()

      --clip area
      content:attrClip(nLeft, nTop, nWidth, nHeight)
      --compose scroll
      content:compose(nLeft, nTop, list.scrollContent)
   end

   --unclip area
   content:attrClip(clipX, clipY, clipW, clipH)
   content:attrColor(nR, nG, nB, nA)
end

function Window:composeListEPG(list, state, content)
   if (content == nil) then
      content = self.layers[list.z].content
   end

   if (#list.nav.columnLimit < 1) then
      print("##### [GUILT] WARNING composeList: list data not loaded!!!")
      return
   end

   --update area
   list:updateArea()

   --set line page position and size
   list.page.linePosition = 1
   list.page.intervalTop = math.floor(list.area.height / list.page.lineSize)

   if (list.page.lineSize > list.nav.lineLimit) then
      list.page.lineSize = list.nav.lineLimit
   end

   --set column page position and size
   if (list.page.hideScroll) then
      list.page.intervalLeft = list.area.width / list.page.columnSize
   else
      list.page.intervalLeft = (list.area.width - list.scroll.width) / list.page.columnSize
   end

   --update line position
   if (list.nav.curLine > list.page.lineSize) then
      list.page.linePosition = list.nav.curLine - list.page.lineSize + 1
   end

   --update column position
   if (list.nav.curColumn > list.page.columnSize) then
      list.page.columnPosition[list.nav.curLine] = list.nav.curColumn - list.page.columnSize + 1
   end
   --compose focus content
   self:composeFocusContentEPG(list)

   --compose scroll content
   self:composeScrollContentEPG(list)

   --compose list content
   self:composeListContentEPG(list)

   local clipX, clipY, clipW, clipH = content:attrClip()
   local nR, nG, nB, nA = content:attrColor()

   --clip area
   content:attrClip(list.area.left, list.area.top, list.area.width, list.area.height)

   --draw background
   if (list.color[4] > 0) then
      content:attrColor(unpack(list.color))
      content:drawRect('fill', list.area.left, list.area.top, list.area.width, list.area.height)
   end

   if (list.isFocusFront) then
      local nLeft = list.area.left
      local nTop = list.area.top

      content:attrClip(list.area.left, list.area.top, list.page.columnSize * list.page.intervalLeft, list.page.lineSize * list.page.intervalTop)
      content:compose(nLeft, nTop, list.listContent)

      nLeft = list.area.left + ((list.nav.curColumn - list.page.columnPosition[list.nav.curLine]) * list.page.intervalLeft)
      nTop = list.area.top + ((list.nav.curLine - list.page.linePosition) * list.page.intervalTop)

      content:attrClip(nLeft, nTop, list.page.intervalLeft, list.page.intervalTop)
      content:compose(nLeft, nTop, list.focusContent)
   else
      local nLeft = list.area.left + ((list.nav.curColumn - list.page.columnPosition[list.nav.curLine]) * list.page.intervalLeft)
      local nTop = list.area.top + ((list.nav.curLine - list.page.linePosition) * list.page.intervalTop)

      content:attrClip(nLeft, nTop, list.page.intervalLeft, list.page.intervalTop)
      content:compose(nLeft, nTop, list.focusContent)

      nLeft = list.area.left
      nTop = list.area.top

      content:attrClip(list.area.left, list.area.top, list.page.columnSize * list.page.intervalLeft, list.page.lineSize * list.page.intervalTop)
      content:compose(nLeft, nTop, list.listContent)
   end

   nLeft = list.area.left
   nTop = list.area.top

   --check scroll
   if (list.scrollContent) then
      nLeft = list.area.left + list.area.width - list.scroll.width
      nTop = list.area.top + math.floor((list.page.linePosition - 1) * (list.area.height / list.nav.lineLimit))

      local nWidth, nHeight = list.scrollContent:attrSize()

      --clip area
      content:attrClip(nLeft, nTop, nWidth, nHeight)
      --compose scroll
      content:compose(nLeft, nTop, list.scrollContent)
   end

   --unclip area
   content:attrClip(clipX, clipY, clipW, clipH)
   content:attrColor(nR, nG, nB, nA)
end

function Window:composeListContent(list)
   --create canvas
   if (not list.listContent) then
      local nWidth = list.page.intervalLeft * list.page.columnSize
      local nHeight = list.page.intervalTop * list.page.lineSize
      list.listContent = canvas:new(nWidth, nHeight)
   end

   --check if has box element
   if (list.children.componentType ~= "Box") then
      print("##### [GUILT] WARNING composeListContent: element box not loaded!!!")
      return
   end

   --check if has elements inside
   if (#list.children.children < 1) then
      print("##### [GUILT] WARNING composeListContent: there is no element inside box!!!")
      return
   end

   --clear
   list.listContent:attrColor(0, 0, 0, 0)
   list.listContent:clear()

   local nStartLine = list.page.linePosition
   local nEndLine = nStartLine + list.page.lineSize - 1
   for i = nStartLine, nEndLine, 1 do
      local nStartColumn = list.page.columnPosition[i]
      local nEndColumn = list.nav.columnLimit[i]
      for j = nStartColumn, nEndColumn, 1 do
      
         --define position
         local nLeft = ((j - nStartColumn) * list.page.intervalLeft)
         local nTop = ((i - nStartLine) * list.page.intervalTop)

         --set position
         list.children:setArea({
            left = nLeft,
            top = nTop,
            width = list.page.intervalLeft,
            height = list.page.intervalTop
         })

         --draw background
         if (list.children.color[4] > 0) then
            list.listContent:attrColor(unpack(list.children.color))
            list.listContent:drawRect(
               'fill',
               list.children.area.left,
               list.children.area.top,
               list.children.area.width,
               list.children.area.height
            )
         end

         local nPos = 1
         --draw elements
         if (list.dataIndex) then
            for k = 1, #list.dataIndex do
               if (type(list.data[i][j][list.dataIndex[k]]) == 'string' and list.children.children[nPos]) then
                  local sState = 'activated'

                  --check if activated
                  if (not list.isActivated) then
                     sState = 'deactivated'
                  end

                  --set selected
                  if (list.nav.selLine == i and list.nav.selColumn == j) then
                     sState = 'selected'
                  elseif (list.nav.curLine == i and list.nav.curColumn == j) then
                     sState = 'focused'
                  end

                  local tComponent = list.children.children[nPos]
                  local nWidth = tComponent.area.width
                  local nHeight = tComponent.area.height
                  --compose label
                  if (tComponent.componentType == "Label") then
                     tComponent:setText(list.data[i][j][list.dataIndex[k]])
                     self:composeLabel(tComponent, sState, list.listContent)
                  --compose image
                  elseif (tComponent.componentType == "Image") then
                     tComponent:setFileName(list.data[i][j][list.dataIndex[k]])
                     self:composeImage(tComponent, sState, list.listContent)
                  elseif (tComponent.componentType == "Rectangle") then
                     self:composeRect(tComponent, list.listContent)
                  end

                  if (nWidth < 1) then
                     tComponent.area.width = nWidth
                  end
                  if (nHeight < 1) then
                     tComponent.area.height = nHeight
                  end

                  nPos = nPos + 1

               elseif(type(list.data[i][j][list.dataIndex[k]]) == 'boolean' and list.children.children[nPos]) then
                  local sState = 'activated'

                  --set selected
                  if (list.data[i][j][list.dataIndex[k]]) then
                     sState = 'selected'
                  end

                  --check if activated
                  if (not list.isActivated) then
                     sState = 'deactivated'
                  end

                  --if (list.nav.curLine == i and list.nav.curColumn == j) then
                     --sState = 'focused'
                  --end

                  local tComponent = list.children.children[nPos]
                  local nWidth = tComponent.area.width
                  local nHeight = tComponent.area.height
                  --compose label
                  if (tComponent.componentType == "Label") then
                     self:composeLabel(tComponent, sState, list.listContent)
                  --compose image
                  elseif (tComponent.componentType == "Image") then
                     self:composeImage(tComponent, sState, list.listContent)
                  elseif (tComponent.componentType == "Rectangle") then
                     if (list.data[i][j][list.dataIndex[k]]) then
                        self:composeRect(tComponent, list.listContent)
                     end
                  end

                  if (nWidth < 1) then
                     tComponent.area.width = nWidth
                  end
                  if (nHeight < 1) then
                     tComponent.area.height = nHeight
                  end

                  nPos = nPos + 1
               end
            end
         else
            for k, v in pairs(list.data[i][j]) do

               if (type(v) == 'string' and list.children.children[nPos]) then
                  local sState = 'activated'

                  --check if activated
                  if (not list.isActivated) then
                     sState = 'deactivated'
                  end

                  --set selected
                  if (list.nav.selLine == i and list.nav.selColumn == j) then
                     sState = 'selected'
                  elseif (list.nav.curLine == i and list.nav.curColumn == j) then
                     sState = 'focused'
                  end

                  local tComponent = list.children.children[nPos]
                  local nWidth = tComponent.area.width
                  local nHeight = tComponent.area.height
                  --compose label
                  if (tComponent.componentType == "Label") then
                     tComponent:setText(v)
                     self:composeLabel(tComponent, sState, list.listContent)
                  --compose image
                  elseif (tComponent.componentType == "Image") then
                     tComponent:setFileName(v)
                     self:composeImage(tComponent, sState, list.listContent)
                  elseif (tComponent.componentType == "Rectangle") then
                     self:composeRect(tComponent, list.listContent)
                  end

                  if (nWidth < 1) then
                     tComponent.area.width = nWidth
                  end
                  if (nHeight < 1) then
                     tComponent.area.height = nHeight
                  end

                  nPos = nPos + 1

               elseif(type(v) == 'boolean' and list.children.children[nPos]) then
                  local sState = 'activated'

                  --set selected
                  if (v) then
                     sState = 'selected'
                  end

                  --check if activated
                  if (not list.isActivated) then
                     sState = 'deactivated'
                  end

                  if (list.nav.curLine == i and list.nav.curColumn == j) then
                     sState = 'focused'
                  end

                  local tComponent = list.children.children[nPos]
                  local nWidth = tComponent.area.width
                  local nHeight = tComponent.area.height
                  --compose label
                  if (tComponent.componentType == "Label") then
                     self:composeLabel(tComponent, sState, list.listContent)
                  --compose image
                  elseif (tComponent.componentType == "Image") then
                     self:composeImage(tComponent, sState, list.listContent)
                  elseif (tComponent.componentType == "Rectangle") then
                     self:composeRect(tComponent, list.listContent)
                  end

                  if (nWidth < 1) then
                     tComponent.area.width = nWidth
                  end
                  if (nHeight < 1) then
                     tComponent.area.height = nHeight
                  end

                  nPos = nPos + 1
               end
            end
         end
      end
   end
end

function Window:composeListContentBase(list)
   --create canvas
   if (not list.listContent) then
      local nWidth = list.page.intervalLeft * list.page.columnSize
      local nHeight = list.page.intervalTop * list.page.lineSize
      list.listContent = canvas:new(nWidth, nHeight)
   end

   --clear
   list.listContent:attrColor(0, 0, 0, 0)
   list.listContent:clear()

   local nStartLine = list.page.linePosition
   local nEndLine = nStartLine + list.page.lineSize - 1
   local nStartColumn = list.page.columnPosition
   local nEndColumn = list.nav.columnLimit

   local nStart = 1
   local nEnd = 1

   if ((nEndLine - nStartLine) > 0) then
      nStart = nStartLine
      nEnd = nEndLine
      list.listOrientation = list.orientation.vertical
   else
      nStart = nStartColumn
      nEnd = nEndColumn
      list.listOrientation = list.orientation.horizontal
   end

   for i = nStart, nEnd, 1 do
      --define orientation
      local nLeft = 0
      local nTop = 0

      if (list.listOrientation == list.orientation.vertical) then
         nTop = ((i - nStart) * list.page.intervalTop)
      else
         nLeft = ((i - nStart) * list.page.intervalLeft)
      end

      --set position
      list.children:setArea({
         left = nLeft,
         top = nTop,
         width = list.page.intervalLeft,
         height = list.page.intervalTop
      })

      local nPos = 1
      --draw elements
      for k = 1, #list.dataIndex do
         if (list.children.children[nPos]) then
            local sState = 'activated'

            local tComponent = list.children.children[nPos]
            local nWidth = tComponent.area.width
            local nHeight = tComponent.area.height

            --compose label
            if (tComponent.componentType == "Label") then
               tComponent:setText(list.data[i][list.dataIndex[k]])
               self:composeLabel(tComponent, sState, list.listContent)
            --compose image
            elseif (tComponent.componentType == "Image") then
               tComponent:setFileName(list.data[i][list.dataIndex[k]])
               self:composeImage(tComponent, sState, list.listContent)
            end

            if (nWidth < 1) then
               tComponent.area.width = nWidth
            end
            if (nHeight < 1) then
               tComponent.area.height = nHeight
            end

            nPos = nPos + 1
         end
      end
   end

   if (not list.firstContent) then
      list.firstContent = canvas:new(list.listContent:attrSize())
      list.firstContent:attrColor(0, 0, 0, 0)
      list.firstContent:clear()
      list.firstContent:compose(0, 0, list.listContent)
   end

   if ((list.nav.curColumn == list.nav.columnLimit and list.nav.curLine == list.nav.lineLimit) and not list.lastContent) then
         list.lastContent = canvas:new(list.listContent:attrSize())
         list.lastContent:attrColor(0, 0, 0, 0)
         list.lastContent:clear()
         list.lastContent:compose(0, 0, list.listContent)
   end
end

function Window:composeListContentHUB(list)
   --create canvas
   if (not list.listContent) then
      local nWidth = list.page.intervalLeft * list.page.columnSize
      local nHeight = list.page.intervalTop * list.page.lineSize
      list.listContent = canvas:new(nWidth, nHeight)
   end

   --clear
   list.listContent:attrColor(0, 0, 0, 0)
   list.listContent:clear()

   local nStartLine = list.page.linePosition
   local nEndLine = nStartLine + list.page.lineSize - 1
   local nStartColumn = list.page.columnPosition
   local nEndColumn = list.nav.columnLimit

   for i = nStartLine, nEndLine, 1 do
      for j = nStartColumn, nEndColumn, 1 do

         local nLeft = ((j - nStartColumn) * list.page.intervalLeft)
         local nTop = ((i - nStartLine) * list.page.intervalTop)

         --set position
         list.children:setArea({
            left = nLeft,
            top = nTop,
            width = list.page.intervalLeft,
            height = list.page.intervalTop
         })

         local nPos = 1
         --draw elements
         for k = 1, #list.dataIndex do
            if (list.children.children[nPos]) then
               local sState = 'activated'

               local tComponent = list.children.children[nPos]
               local nWidth = tComponent.area.width
               local nHeight = tComponent.area.height

               local index = ((i - 1) * nEndColumn) + (j - 1) + 1

               if (index > #list.data) then
                  break
               end

               --compose label
               if (tComponent.componentType == "Label") then
                  tComponent:setText(list.data[index][list.dataIndex[k]])
                  self:composeLabel(tComponent, sState, list.listContent)
               --compose image
               elseif (tComponent.componentType == "Image") then
                  tComponent:setFileName(list.data[index][list.dataIndex[k]])
                  self:composeImage(tComponent, sState, list.listContent)
               end

               if (nWidth < 1) then
                  tComponent.area.width = nWidth
               end
               if (nHeight < 1) then
                  tComponent.area.height = nHeight
               end

               nPos = nPos + 1
            end
         end
      end
   end

   if (not list.cacheContent[self.currentPage]) then
      list.cacheContent[list.currentPage] = canvas:new(list.listContent:attrSize())
      list.cacheContent[list.currentPage]:attrColor(0, 0, 0, 0)
      list.cacheContent[list.currentPage]:clear()
      list.cacheContent[list.currentPage]:compose(0, 0, list.listContent)
   end
end

function Window:composeListContentEPG(list)
   --create canvas
   if (not list.listContent) then
      local nWidth = list.page.intervalLeft * list.page.columnSize
      local nHeight = list.page.intervalTop * list.page.lineSize
      list.listContent = canvas:new(nWidth, nHeight)
   end

   --check if has box element
   if (list.children.componentType ~= "Box") then
      print("##### [GUILT] WARNING composeListContent: element box not loaded!!!")
      return
   end

   --check if has elements inside
   if (#list.children.children < 1) then
      print("##### [GUILT] WARNING composeListContent: there is no element inside box!!!")
      return
   end

   --clear
   list.listContent:attrColor(0, 0, 0, 0)
   list.listContent:clear()

   local nStartLine = list.page.linePosition
   local nEndLine = nStartLine + list.page.lineSize - 1
   for i = nStartLine, nEndLine, 1 do
      local nStartColumn = list.page.columnPosition[i]
      local nEndColumn = list.nav.columnLimit[i]
      for j = nStartColumn, nEndColumn, 1 do
      
         --define position
         local nLeft = ((j - nStartColumn) * list.page.intervalLeft)
         local nTop = ((i - nStartLine) * list.page.intervalTop)

         --set position
         list.children:setArea({
            left = nLeft,
            top = nTop,
            width = list.page.intervalLeft,
            height = list.page.intervalTop
         })

         --draw background
         if (list.children.color[4] > 0) then
            list.listContent:attrColor(unpack(list.children.color))
            list.listContent:drawRect(
               'fill',
               list.children.area.left,
               list.children.area.top,
               list.children.area.width,
               list.children.area.height
            )
         end

         local nPos = 1
         --draw elements
         if (list.dataIndex) then
            for k = 1, #list.dataIndex do
               local sState = 'activated'

               local tComponentBase = list.children.children[nPos]

               -- Here the magic begins
               local tComponent = _G[tComponentBase.componentType]:new()

               tComponent:setAnchors(tComponentBase.anchors)
               if (tComponent.componentType == "Label") then
                  tComponent:setText(list.data[i][j][list.dataIndex[k]])
               elseif (tComponent.componentType == "Image") then
                  if (tComponentBase.fileName == '') then
                     tComponent:setFileName(list.data[i][j][list.dataIndex[k]])
                  else
                     tComponent:setFileName(tComponentBase.fileName)
                  end
               end

               if (tComponentBase.behavior) then
                  tComponentBase.behavior(tComponent, list, list.data[i][j][list.dataIndex[k]], i, j, false)
               end

               local nWidth = tComponent.area.width
               local nHeight = tComponent.area.height

               if (tComponent.componentType == "Label") then
                  self:composeLabel(tComponent, sState, list.listContent)
               elseif (tComponent.componentType == "Image") then
                  self:composeImage(tComponent, sState, list.listContent)
               end

               if (nWidth < 1) then
                  tComponent.area.width = nWidth
               end
               if (nHeight < 1) then
                  tComponent.area.height = nHeight
               end

               nPos = nPos + 1
            end
         end
      end
   end
end

function Window:composeFocusContent(list)
   --load focus bar
   list.focusContent = canvas:new(list.page.intervalLeft, list.page.intervalTop)

   local newBorder = list.border
   local newSlice = list.slice

   if (not list.isActivated) then
      newBorder = list.borderDisabled
      newSlice = list.sliceDisabled
   end

   if (newBorder and newSlice) then

      if (newBorder.componentType == "Image") and (newSlice.componentType == "Image") then
         local gradientBorder = canvas:new(newBorder.fileName)

         local nWidth, nHeight = gradientBorder:attrSize()

         gradientBorder:attrScale(nWidth, list.page.intervalTop)
         list.focusContent:compose(0, 0, gradientBorder)

         local gradientSlice = canvas:new(newSlice.fileName)
         gradientSlice:attrScale(list.page.intervalLeft - (nWidth * 2), list.page.intervalTop)
         list.focusContent:compose(nWidth, 0, gradientSlice)

         gradientBorder:attrFlip(true, false)
         list.focusContent:compose(list.page.intervalLeft - nWidth, 0, gradientBorder)

         gradientBorder = nil
         gradientSlice = nil
      elseif (newBorder.componentType == "Rectangle") and (newSlice.componentType == "Image") then
         --draw background
         if (newBorder.color[4] > 0) then
            list.focusContent:attrColor(unpack(newBorder.color))
            list.focusContent:drawRect('fill', 0, 0, list.page.intervalLeft, list.page.intervalTop)
         end

         local gradientSlice = canvas:new(newSlice.fileName)
         local nWidth, nHeight = gradientSlice:attrSize()

         gradientSlice:attrScale(list.page.intervalLeft, nHeight)
         list.focusContent:compose(0, 0, gradientSlice)

         gradientSlice = nil
      end
   elseif (list.boxFocus) then
      list.boxFocus:setArea({
         top = 0,
         left = 0,
         width = list.page.intervalLeft,
         height = list.page.intervalTop
      })

      for i = 1, #list.boxFocus.children do
         if (list.boxFocus.children[i].componentType == "Rectangle") then
            self:composeRect(list.boxFocus.children[i], list.focusContent)
         elseif (list.boxFocus.children[i].componentType == "Image") then
            self:composeImage(list.boxFocus.children[i], nil, list.focusContent)
         elseif (list.boxFocus.children[i].componentType == "Label") then
            x, y = list:getCurrentPosition()
            for k, v in pairs(list.data[x][y]) do
               if (type(v) == "string") then
                  list.boxFocus.children[i]:setText(v)
                  break
               end
            end
            self:composeLabel(list.boxFocus.children[i], nil, list.focusContent)
         end
      end
   end
end

function Window:composeFocusContentBase(list)
   --load focus bar
   list.focusContent = canvas:new(list.page.intervalLeft, list.page.intervalTop)

   if (#list.boxFocus.children <= 0) then
      return
   end

   list.boxFocus:setArea({
      top = 0,
      left = 0,
      width = list.page.intervalLeft,
      height = list.page.intervalTop
   })

   for i = 1, #list.boxFocus.children do
      if (list.boxFocus.children[i].componentType == "Rectangle") then
         self:composeRect(list.boxFocus.children[i], list.focusContent)
      elseif (list.boxFocus.children[i].componentType == "Image") then
         self:composeImage(list.boxFocus.children[i], nil, list.focusContent)
      elseif (list.boxFocus.children[i].componentType == "Label") then
         x, y = list:getCurrentPosition()
         for k, v in pairs(list.data[x][y]) do
            if (type(v) == "string") then
               list.boxFocus.children[i]:setText(v)
               break
            end
         end
         self:composeLabel(list.boxFocus.children[i], nil, list.focusContent)
      end
   end
end

function Window:composeFocusContentHUB(list)
   --load focus bar
   list.focusContent = canvas:new(list.page.intervalLeft, list.page.intervalTop)

   if (#list.boxFocus.children <= 0) then
      return
   end

   list.boxFocus:setArea({
      top = 0,
      left = 0,
      width = list.page.intervalLeft,
      height = list.page.intervalTop
   })

   for i = 1, #list.boxFocus.children do
      if (list.boxFocus.children[i].componentType == "Rectangle") then
         self:composeRect(list.boxFocus.children[i], list.focusContent)
      elseif (list.boxFocus.children[i].componentType == "Image") then
         self:composeImage(list.boxFocus.children[i], nil, list.focusContent)
      elseif (list.boxFocus.children[i].componentType == "Label") then
         x, y = list:getCurrentPosition()
         for k, v in pairs(list.data[x][y]) do
            if (type(v) == "string") then
               list.boxFocus.children[i]:setText(v)
               break
            end
         end
         self:composeLabel(list.boxFocus.children[i], nil, list.focusContent)
      end
   end
end

function Window:composeEditFocusContentHUB(list)
   --load focus bar
   list.editContent = canvas:new(list.page.intervalLeft, list.page.intervalTop)
   list.editContent:attrColor(0, 0, 0, 0)
   list.editContent:clear()

   local nTop = ((list.nav.curLine - list.page.linePosition) * list.page.intervalTop)
   local nLeft = ((list.nav.curColumn - list.page.columnPosition) * list.page.intervalLeft)

   local cropX, cropY, cropW, cropH = list.listContent:attrCrop()
   list.listContent:attrCrop(nLeft, nTop, list.page.intervalLeft, list.page.intervalTop)
   list.editContent:compose(0, 0, list.listContent)
   list.editContent:compose(0, 0, list.lastFocusContent)
   list.listContent:attrCrop(cropX, cropY, cropW, cropH)
end

function Window:composeFocusContentEPG(list)
   --load focus bar
   list.focusContent = canvas:new(list.page.intervalLeft, list.page.intervalTop)

   local newBorder = list.border
   local newSlice = list.slice

   if (not list.isActivated) then
      newBorder = list.borderDisabled
      newSlice = list.sliceDisabled
   end

   if (newBorder and newSlice) then

      if (newBorder.componentType == "Image") and (newSlice.componentType == "Image") then
         local gradientBorder = canvas:new(newBorder.fileName)

         local nWidth, nHeight = gradientBorder:attrSize()

         gradientBorder:attrScale(nWidth, list.page.intervalTop)
         list.focusContent:compose(0, 0, gradientBorder)

         local gradientSlice = canvas:new(newSlice.fileName)
         gradientSlice:attrScale(list.page.intervalLeft - (nWidth * 2), list.page.intervalTop)
         list.focusContent:compose(nWidth, 0, gradientSlice)

         gradientBorder:attrFlip(true, false)
         list.focusContent:compose(list.page.intervalLeft - nWidth, 0, gradientBorder)

         gradientBorder = nil
         gradientSlice = nil
      elseif (newBorder.componentType == "Rectangle") and (newSlice.componentType == "Image") then
         --draw background
         if (newBorder.color[4] > 0) then
            list.focusContent:attrColor(unpack(newBorder.color))
            list.focusContent:drawRect('fill', 0, 0, list.page.intervalLeft, list.page.intervalTop)
         end

         local gradientSlice = canvas:new(newSlice.fileName)
         local nWidth, nHeight = gradientSlice:attrSize()

         gradientSlice:attrScale(list.page.intervalLeft, nHeight)
         list.focusContent:compose(0, 0, gradientSlice)

         gradientSlice = nil
      end
   elseif (list.boxFocus) then
      list.boxFocus:setArea({
         top = 0,
         left = 0,
         width = list.page.intervalLeft,
         height = list.page.intervalTop
      })

      for i = 1, #list.boxFocus.children do
         if (list.boxFocus.children[i].componentType == "Rectangle") then
            self:composeRect(list.boxFocus.children[i], list.focusContent)
         elseif (list.boxFocus.children[i].componentType == "Image") then
            self:composeImage(list.boxFocus.children[i], nil, list.focusContent)
         elseif (list.boxFocus.children[i].componentType == "Label") then
            x, y = list:getCurrentPosition()
            for k, v in pairs(list.data[x][y]) do
               if (type(v) == "string") then
                  list.boxFocus.children[i]:setText(v)
                  break
               end
            end
            self:composeLabel(list.boxFocus.children[i], nil, list.focusContent)
         end
      end

      if (list.focusElement) then

         list.children:setArea({
            left = 0,
            top = 0,
            width = list.page.intervalLeft,
            height = list.page.intervalTop
         })

         nPos = 1
         for k = 1, #list.dataIndex do
            local sState = 'activated'

            local tComponentBase = list.children.children[nPos]

            -- Here the magic begins
            local tComponent = _G[tComponentBase.componentType]:new()

            tComponent:setAnchors(tComponentBase.anchors)
            if (tComponent.componentType == "Label") then
               tComponent:setText(list.data[list.nav.curLine][list.nav.curColumn][list.dataIndex[k]])
            elseif (tComponent.componentType == "Image") then
               if (tComponentBase.fileName == '') then
                  tComponent:setFileName(list.data[list.nav.curColumn][list.nav.curColumn][list.dataIndex[k]])
               else
                  tComponent:setFileName(tComponentBase.fileName)
               end
            end

            if (tComponentBase.behavior) then
               tComponentBase.behavior(tComponent, list, list.data[list.nav.curLine][list.nav.curColumn][list.dataIndex[k]], list.nav.curLine, list.nav.curColumn, true)
            end

            local nWidth = tComponent.area.width
            local nHeight = tComponent.area.height

            if (tComponent.componentType == "Label" and tComponentBase.inFocus) then
               self:composeLabel(tComponent, sState, list.focusContent)
            elseif (tComponent.componentType == "Image" and tComponentBase.inFocus) then
               self:composeImage(tComponent, sState, list.focusContent)
            end

            if (nWidth < 1) then
               tComponent.area.width = nWidth
            end
            if (nHeight < 1) then
               tComponent.area.height = nHeight
            end

            nPos = nPos + 1
         end
      end
   end
end

function Window:composeScrollContent(list)
   --create scroll
   if (list.page.lineSize < list.nav.lineLimit) then
      local nHalfWidth = list.scroll.width / 2
      local nHeight = math.floor(list.area.height / (list.nav.lineLimit / list.page.lineSize))

      list.scrollContent = canvas:new(list.scroll.width, nHeight)

      list.scrollContent:attrColor(unpack(list.scroll.color))
      list.scrollContent:drawRect('fill', 0, list.scroll.width, list.scroll.width, nHeight - list.scroll.width - list.scroll.width)
      list.scrollContent:drawEllipse('fill', nHalfWidth, list.scroll.width, nHalfWidth, nHalfWidth, 270, 90)
      list.scrollContent:drawEllipse('fill', nHalfWidth, nHeight - list.scroll.width, nHalfWidth, nHalfWidth, 90, 270)
   end
end

function Window:composeScrollContentBase(list)
   --create scroll
   if (list.page.lineSize < list.nav.lineLimit) then
      local nHalfWidth = list.scroll.width / 2
      local nHeight = math.floor(list.area.height / (list.nav.lineLimit / list.page.lineSize))

      list.scrollContent = canvas:new(list.scroll.width, nHeight)

      list.scrollContent:attrColor(unpack(list.scroll.color))
      list.scrollContent:drawRect('fill', 0, list.scroll.width, list.scroll.width, nHeight - list.scroll.width - list.scroll.width)
      list.scrollContent:drawEllipse('fill', nHalfWidth, list.scroll.width, nHalfWidth, nHalfWidth, 270, 90)
      list.scrollContent:drawEllipse('fill', nHalfWidth, nHeight - list.scroll.width, nHalfWidth, nHalfWidth, 90, 270)
   end
end

function Window:composeScrollContentHUB(list)
   --create scroll
   if (list.page.lineSize < list.nav.lineLimit) then
      local nHalfWidth = list.scroll.width / 2
      local nHeight = math.floor(list.area.height / (list.nav.lineLimit / list.page.lineSize))

      list.scrollContent = canvas:new(list.scroll.width, nHeight)

      list.scrollContent:attrColor(unpack(list.scroll.color))
      list.scrollContent:drawRect('fill', 0, list.scroll.width, list.scroll.width, nHeight - list.scroll.width - list.scroll.width)
      list.scrollContent:drawEllipse('fill', nHalfWidth, list.scroll.width, nHalfWidth, nHalfWidth, 270, 90)
      list.scrollContent:drawEllipse('fill', nHalfWidth, nHeight - list.scroll.width, nHalfWidth, nHalfWidth, 90, 270)
   end
end

function Window:composeScrollContentEPG(list)
   --create scroll
   if (list.page.lineSize < list.nav.lineLimit) then
      local nHalfWidth = list.scroll.width / 2
      local nHeight = math.floor(list.area.height / (list.nav.lineLimit / list.page.lineSize))

      list.scrollContent = canvas:new(list.scroll.width, nHeight)

      list.scrollContent:attrColor(unpack(list.scroll.color))
      list.scrollContent:drawRect('fill', 0, list.scroll.width, list.scroll.width, nHeight - list.scroll.width - list.scroll.width)
      list.scrollContent:drawEllipse('fill', nHalfWidth, list.scroll.width, nHalfWidth, nHalfWidth, 270, 90)
      list.scrollContent:drawEllipse('fill', nHalfWidth, nHeight - list.scroll.width, nHalfWidth, nHalfWidth, 90, 270)
   end
end

function Window:composeProgressBar(progressBar) 
   progressBar:updateArea()

   progressBar.backContent = canvas:new(progressBar.area.width, progressBar.area.height)

   local tmpBox = Box:new({top = 0, left = 0, width = progressBar.area.width, height = progressBar.area.height})

   local bgLeft = Image:new({fileName = progressBar.backGround[1]})
   bgLeft:setAnchors({top = tmpBox.top, left = tmpBox.left})
   local bgRight = Image:new({fileName = progressBar.backGround[3]})
   bgRight:setAnchors({top = tmpBox.top, right = tmpBox.right})
   local bgCenter = Image:new({fileName = progressBar.backGround[2]})
   bgCenter:setAnchors({top = tmpBox.top, left = bgLeft.right, right = bgRight.left})

   self:composeImage(bgLeft, nil, progressBar.backContent)
   self:composeImage(bgRight, nil, progressBar.backContent)
   self:composeImage(bgCenter, nil, progressBar.backContent)

   self.layers[progressBar.z].content:compose(progressBar.area.left, progressBar.area.top, progressBar.backContent)

   progressBar.barContent = canvas:new(progressBar.area.width, progressBar.area.height)

   tmpBox = Box:new({top = 1, left = 0, width = progressBar.area.width, height = progressBar.area.height - 1})

   local fgLeft = Image:new({fileName = progressBar.foreGround[1]})
   fgLeft:setAnchors({top = tmpBox.top, left = tmpBox.left})
   local fgRight = Image:new({fileName = progressBar.foreGround[3]})
   fgRight:setAnchors({top = tmpBox.top, right = tmpBox.right})
   local fgCenter = Image:new({fileName = progressBar.foreGround[2]})
   fgCenter:setAnchors({top = tmpBox.top, left = fgLeft.right, right = fgRight.left})

   self:composeImage(fgLeft, nil, progressBar.barContent)
   self:composeImage(fgRight, nil, progressBar.barContent)
   self:composeImage(fgCenter, nil, progressBar.barContent)

   local newWidth = math.floor((progressBar.area.width / progressBar.maxValue) * progressBar.value)

   local clipX, clipY, clipW, clipH = self.layers[progressBar.z].content:attrClip()
   self.layers[progressBar.z].content:attrClip(progressBar.area.left, progressBar.area.top, newWidth, progressBar.area.height)
   self.layers[progressBar.z].content:compose(progressBar.area.left, progressBar.area.top, progressBar.barContent)
   self.layers[progressBar.z].content:attrClip(clipX, clipY, clipW, clipH)

   if (not progressBar.noLabel) then
      progressBar.label:setAnchors({centerIn = progressBar})
      self:composeLabel(progressBar.label, nil, self.layers[progressBar.z].content)
   end
end

function Window:composeSignalMeter(signalMeter)
   signalMeter:updateArea()

   local newHeight = math.floor((signalMeter.area.height / signalMeter.maxValue) * (100 - signalMeter.value))

   signalMeter.backContent = canvas:new(signalMeter.area.width, signalMeter.area.height)

   local tmpBox = Box:new({top = 0, left = 0, width = signalMeter.area.width, height = signalMeter.area.height})

   local bg = Image:new({fileName = signalMeter.backGround})
   bg:setAnchors({centerIn = tmpBox})

   self:composeImage(bg, nil, signalMeter.backContent)

   local clipX, clipY, clipW, clipH = self.layers[signalMeter.z].content:attrClip()
   self.layers[signalMeter.z].content:attrClip(signalMeter.area.left, signalMeter.area.top, signalMeter.area.width, newHeight)
   self.layers[signalMeter.z].content:attrColor(0, 0, 0, 0)
   self.layers[signalMeter.z].content:clear()
   self.layers[signalMeter.z].content:compose(signalMeter.area.left, signalMeter.area.top, signalMeter.backContent)
   self.layers[signalMeter.z].content:attrClip(clipX, clipY, clipW, clipH)

   signalMeter.barContent = canvas:new(signalMeter.area.width, signalMeter.area.height)

   tmpBox = Box:new({top = 0, left = 0, width = signalMeter.area.width, height = signalMeter.area.height})

   local fg = Image:new({fileName = signalMeter.foreGround})
   fg:setAnchors({centerIn = tmpBox})

   self:composeImage(fg, nil, signalMeter.barContent)


   clipX, clipY, clipW, clipH = self.layers[signalMeter.z].content:attrClip()
   self.layers[signalMeter.z].content:attrClip(signalMeter.area.left, signalMeter.area.top + newHeight, signalMeter.area.width, signalMeter.area.height - newHeight)
   self.layers[signalMeter.z].content:compose(signalMeter.area.left, signalMeter.area.top, signalMeter.barContent)
   self.layers[signalMeter.z].content:attrClip(clipX, clipY, clipW, clipH)

   if (not signalMeter.noLabel) then
      signalMeter.label:setAnchors({centerIn = signalMeter})
      self:composeLabel(signalMeter.label, nil, self.layers[signalMeter.z].content)
   end
end

function Window:composeIndexPage(indexPage) 
   content = self.layers[indexPage.z].content

   local nPages = indexPage.numberPages
   local nMax = indexPage.maxPage
   
   local nWidth = (25 * nMax - 10)
   local nHeight = 19

   indexPage:setArea({
      width = nWidth,
      height = nHeight
   })
   
   indexPage:updateArea()

   --indexPage.content = canvas:new(nWidth, nHeight)

   local tPages = {}
   local nLeft = indexPage.area.left

   for i = 1, nPages, 1 do
      if (i ~= indexPage.selected) then
         tPages[i] = Image:new({
            fileName = indexPage.disabledPage
         })
      else
         tPages[i] = Image:new({
            fileName = indexPage.activePage
         })
      end
      tPages[i]:setArea({
         left = nLeft,
         top = indexPage.area.top
      })
      self:composeImage(tPages[i], nil, content)
      nLeft = nLeft + 25
   end
end

function Window:composeTextBox(textBox)
   content = self.layers[textBox.z].content

   textBox:updateArea()

   textBox.label:setArea({
      top = 0,
      left = 0
   })

   -- workaround to get the text lines
   local tmpCanvas = canvas:new(1, 1)
   self:composeLabel(textBox.label, nil, tmpCanvas)
   local nLabelHeight = select(2, tmpCanvas:measureText(textBox.label.text)) - 5 --@TODO change Label component
   textBox.lineSize = nLabelHeight
   tmpCanvas = nil

   textBox.label:setArea({
      height = nLabelHeight * textBox.label.textLines
   })
   local nShownLines = textBox.area.height/(nLabelHeight)
   
   textBox.textContent =  canvas:new(textBox.area.width, textBox.label.area.height)
   self:composeLabel(textBox.label, nil, textBox.textContent)
   
   local clipX, clipY, clipW, clipH = content:attrClip()
   content:attrClip(textBox.area.left, textBox.area.top, textBox.area.width, textBox.area.height)
   content:compose(textBox.area.left, textBox.area.top -5, textBox.textContent) --@TODO "-5" change Label component
   content:attrClip(clipX, clipY, clipW, clipH)
   
   if (textBox.label.area.height > textBox.area.height) then
      textBox.maxValue = textBox.label.textLines - math.ceil(nShownLines)
   end

   --compose scroll content
   self:composeTextBoxScroll(textBox)

   --check scroll
   if (textBox.scrollContent) then
      nLeft = textBox.area.left + textBox.area.width + 10
      nTop = textBox.area.top 

      local nWidth, nHeight = textBox.scrollContent:attrSize()

      --clip area
      content:attrClip(nLeft, nTop, nWidth, nHeight)
      --compose scroll
      content:compose(nLeft, nTop, textBox.scrollContent)
   end
end

function Window:composeTextBoxScroll(textBox)
   --create scroll
   if (textBox.label.area.height > textBox.area.height) then
      local nHalfWidth = textBox.scroll.width / 2
      local nHeight = math.floor(textBox.area.height/(textBox.label.area.height/textBox.area.height))
      
      textBox.scrollContent = canvas:new(textBox.scroll.width, nHeight)
      
      textBox.scrollContent:attrColor(unpack(textBox.scroll.color))
      textBox.scrollContent:drawRect('fill', 0, textBox.scroll.width, textBox.scroll.width, nHeight - textBox.scroll.width - textBox.scroll.width)
      textBox.scrollContent:drawEllipse('fill', nHalfWidth, textBox.scroll.width, nHalfWidth, nHalfWidth, 270, 90)
      textBox.scrollContent:drawEllipse('fill', nHalfWidth, nHeight - textBox.scroll.width, nHalfWidth, nHalfWidth, 90, 270)
   end
end


function Window:update(element)
   if (self.layers[element.z]) then
   	local clipX, clipY, clipW, clipH = self.layers[element.z].content:attrClip()
   	--clip area
   	self.layers[element.z].content:attrClip(element.area.left, element.area.top, element.area.width, element.area.height)

      --clear
      self.layers[element.z].content:clear()

   	--unclip area
   	self.layers[element.z].content:attrClip(clipX, clipY, clipW, clipH)

      --compose element
      if (element.visible) then
         if (element.componentType == "Label") then
           self:composeLabel(element)
         elseif (element.componentType == "Rectangle") then
            self:composeRect(element)
         elseif (element.componentType == "Circle") then
            self:composeCircle(element)
         elseif (element.componentType == "Image") then
            self:composeImage(element)
         end
      end

      clipX, clipY, clipW, clipH = self.content:attrClip()
      --clip area
   	self.content:attrClip(element.area.left, element.area.top, element.area.width, element.area.height)

      --clear
      self.content:attrColor(unpack(self.color))
      self.content:clear()

   	--unclip area
   	self.content:attrClip(clipX, clipY, clipW, clipH)

      for i, v in pairs(self.layers) do
         self.content:compose(v.left, v.top, v.content)
      end

      local tArea = {}
      tArea.left = element.area.left + self.area.left
      tArea.top = element.area.top + self.area.top
      tArea.width = element.area.width
      tArea.height = element.area.height

      self.parent:update(tArea, true)

   end
end

function Window:updateList(list, bNeedFocus, bUpdateList, bAvoidFlush)
   local clipX, clipY, clipW, clipH = self.layers[list.z].content:attrClip()

   local tArea = {}

   --calculate left and top
   local nLeft = ((list.nav.curColumn - list.page.columnPosition[list.nav.curLine]) * list.page.intervalLeft)
   local nTop = ((list.nav.curLine - list.page.linePosition) * list.page.intervalTop)

   --clip area
   if (bUpdateList) then
      --update list page
      self:composeListContent(list)

      tArea.left = list.area.left
      tArea.top = list.area.top
      tArea.width = list.area.width
      tArea.height = list.area.height
   else
      --update focused
      if (list.page.updateFocused) then
         --set position
         list.children:setArea({
            left = nLeft,
            top = nTop,
            width = list.page.intervalLeft,
            height = list.page.intervalTop
         })

         local clipFocusedX, clipFocusedY, clipFocusedW, clipFocusedH = list.listContent:attrClip()

         list.listContent:attrClip(nLeft, nTop, list.page.intervalLeft, list.page.intervalTop)
         list.listContent:attrColor(0, 0, 0, 0)
         list.listContent:clear()

         --draw background
         if (list.children.color[4] > 0) then
            list.listContent:attrColor(unpack(list.children.color))
            list.listContent:drawRect(
               'fill',
               nLeft,
               nTop,
               list.page.intervalLeft,
               list.page.intervalTop
            )
         end

         local nPos = 1

         --draw elements
         for k, v in pairs(list.data[list.nav.curLine][list.nav.curColumn]) do

            if (type(v) == 'string' and list.children.children[nPos]) then
               local sState = 'activated'

               --set selected
               if (list.nav.selLine == list.nav.curLine and list.nav.selColumn == list.nav.curColumn) then
                  sState = 'selected'
               elseif (bNeedFocus) then
                  sState = 'focused'
               end

               local tComponent = list.children.children[nPos]
               local nWidth = tComponent.area.width
               local nHeight = tComponent.area.height
               --compose label
               if (tComponent.componentType == "Label") then
                  tComponent:setText(v)
                  self:composeLabel(tComponent, sState, list.listContent)
               --compose image
               elseif (tComponent.componentType == "Image") then
                  tComponent:setFileName(v)
                  self:composeImage(tComponent, sState, list.listContent)
               end

               if (nWidth < 1) then
                  tComponent.area.width = nWidth
               end
               if (nHeight < 1) then
                  tComponent.area.height = nHeight
               end
            end

            nPos = nPos + 1
         end

         --unclip area
         list.listContent:attrClip(clipFocusedX, clipFocusedY, clipFocusedW, clipFocusedH)
      end

      tArea.left = list.area.left + nLeft
      tArea.top = list.area.top + nTop
      tArea.width = list.page.intervalLeft
      tArea.height = list.page.intervalTop
   end

   --clip page
   self.layers[list.z].content:attrClip(tArea.left, tArea.top, tArea.width, tArea.height)

   --clear
--   self.layers[list.z].content:attrColor(unpack(list.color))
   self.layers[list.z].content:clear()

   --check focus

   if (list.isFocusFront) then
      nLeft = list.area.left
      nTop = list.area.top

      self.layers[list.z].content:attrClip(tArea.left, tArea.top, tArea.width, tArea.height)
      self.layers[list.z].content:compose(nLeft, nTop, list.listContent)

      if (bNeedFocus) then

         if (list.dynamicFocus) then
            self:composeFocusContent(list)
         end
         nLeft = ((list.nav.curColumn - list.page.columnPosition[list.nav.curLine]) * list.page.intervalLeft)
         nTop = ((list.nav.curLine - list.page.linePosition) * list.page.intervalTop)

         --clip area
         self.layers[list.z].content:attrClip(list.area.left + nLeft, list.area.top + nTop, list.page.intervalLeft, list.page.intervalTop)
         --compose focus
         self.layers[list.z].content:compose(list.area.left + nLeft, list.area.top + nTop, list.focusContent)
      end
   else
      if (bNeedFocus) then
         nLeft = ((list.nav.curColumn - list.page.columnPosition[list.nav.curLine]) * list.page.intervalLeft)
         nTop = ((list.nav.curLine - list.page.linePosition) * list.page.intervalTop)

         --clip area
         self.layers[list.z].content:attrClip(list.area.left + nLeft, list.area.top + nTop, list.page.intervalLeft, list.page.intervalTop)
         --compose focus
         self.layers[list.z].content:compose(list.area.left + nLeft, list.area.top + nTop, list.focusContent)
      end

      nLeft = list.area.left
      nTop = list.area.top

      self.layers[list.z].content:attrClip(tArea.left, tArea.top, tArea.width, tArea.height)
      self.layers[list.z].content:compose(nLeft, nTop, list.listContent)
   end

   nLeft = list.area.left
   nTop = list.area.top

   --check scroll
   if (list.scrollContent and bUpdateList) then
      nLeft = list.area.left + list.area.width - list.scroll.width
      nTop = list.area.top + math.floor((list.page.linePosition - 1) * (list.area.height / list.nav.lineLimit))

      local nWidth, nHeight = list.scrollContent:attrSize()

      --clip area
      self.layers[list.z].content:attrClip(nLeft, nTop, nWidth, nHeight)
      --compose scroll
      self.layers[list.z].content:compose(nLeft, nTop, list.scrollContent)
   end

   --unclip area
   self.layers[list.z].content:attrClip(clipX, clipY, clipW, clipH)

   tArea.left = tArea.left + self.area.left + self.layers[list.z].left
   tArea.top = tArea.top + self.area.top + self.layers[list.z].top

--   clipX, clipY, clipW, clipH = self.content:attrClip()

--   self.content:attrClip(tArea.left, tArea.top, tArea.width, tArea.height)

   --clear
   self.content:attrColor(unpack(self.color))
   self.content:clear()

   --unclip area
--   self.content:attrClip(clipX, clipY, clipW, clipH)

   for i, v in pairs(self.layers) do
      self.content:compose(v.left, v.top, v.content)
   end

   if (bNeedFocus) then
      local bFlush = not (bAvoidFlush or false)
      self.parent:update(tArea, bFlush)
   else
      self.parent:update(tArea, false)
   end
end

function Window:updateListBase(list, bNeedFocus, bUpdateMode, bAvoidFlush)
   local clipX, clipY, clipW, clipH = self.layers[list.z].content:attrClip()

   local tArea = {}

   --calculate left and top
   local nLeft = 0
   local nTop = 0

   if (list.listOrientation == list.orientation.vertical) then
      nTop = ((list.nav.curLine - list.page.linePosition) * list.page.intervalTop)
   else
      nLeft = ((list.nav.curColumn - list.page.columnPosition) * list.page.intervalLeft)
   end

   --clip area
   if (bUpdateMode == list.updateMode.total) then
      if (list.nav.curColumn == 1 and list.nav.curLine == 1) then
         list.listContent:attrColor(0, 0, 0, 0)
         list.listContent:clear()
         list.listContent:compose(0, 0, list.firstContent)
      elseif (list.lastContent) then
         list.listContent:attrColor(0, 0, 0, 0)
         list.listContent:clear()
         list.listContent:compose(0, 0, list.lastContent)
      else
         self:composeListContentBase(list)
      end


      tArea.left = list.area.left
      tArea.top = list.area.top
      tArea.width = list.area.width
      tArea.height = list.area.height

   elseif (bUpdateMode == list.updateMode.partial) then
      local nWidth = list.page.intervalLeft * list.page.columnSize
      local nHeight = list.page.intervalTop * list.page.lineSize
      local tmpListContent = canvas:new(nWidth, nHeight)
      tmpListContent:attrColor(0, 0, 0, 0)
      tmpListContent:clear()

      local cropX, cropY, cropW, cropH = list.listContent:attrCrop()

      if (list.listOrientation == list.orientation.vertical) then
         if (list.nav.curLine == list.page.linePosition) then
            list.listContent:attrCrop(0, 0, list.page.intervalLeft, nHeight)
            tmpListContent:compose(0, list.page.intervalTop, list.listContent)
            list.listContent:attrCrop(cropX, cropY, cropW, cropH)
            list.listContent:attrColor(0, 0, 0, 0)
            list.listContent:clear()
            list.listContent:compose(0, 0, tmpListContent)
         else
            list.listContent:attrCrop(0, list.page.intervalTop, list.page.intervalLeft, nHeight)
            tmpListContent:compose(0, 0, list.listContent)
            list.listContent:attrCrop(cropX, cropY, cropW, cropH)
            list.listContent:attrColor(0, 0, 0, 0)
            list.listContent:clear()
            list.listContent:compose(0, 0, tmpListContent)
         end
      else
         if (list.nav.curColumn == list.page.columnPosition) then
            list.listContent:attrCrop(0, 0, nWidth, list.page.intervalTop)
            tmpListContent:compose(list.page.intervalLeft, 0, list.listContent)
            list.listContent:attrCrop(cropX, cropY, cropW, cropH)
            list.listContent:attrColor(0, 0, 0, 0)
            list.listContent:clear()
            list.listContent:compose(0, 0, tmpListContent)
         else
            list.listContent:attrCrop(list.page.intervalLeft, 0, nWidth, list.page.intervalTop)
            tmpListContent:compose(0, 0, list.listContent)
            list.listContent:attrCrop(cropX, cropY, cropW, cropH)
            list.listContent:attrColor(0, 0, 0, 0)
            list.listContent:clear()
            list.listContent:compose(0, 0, tmpListContent)
         end
      end

      --set position
      list.children:setArea({
         left = nLeft,
         top = nTop,
         width = list.page.intervalLeft,
         height = list.page.intervalTop
      })

      local clipFocusedX, clipFocusedY, clipFocusedW, clipFocusedH = list.listContent:attrClip()

      list.listContent:attrClip(nLeft, nTop, list.page.intervalLeft, list.page.intervalTop)
      list.listContent:attrColor(0, 0, 0, 0)
      list.listContent:clear()

      local nPos = 1

      --draw elements
      local index = math.max(list.nav.curLine, list.nav.curColumn)
      for k = 1, #list.dataIndex do

         if (list.children.children[nPos]) then
            local sState = 'activated'

            local tComponent = list.children.children[nPos]
            local nWidth = tComponent.area.width
            local nHeight = tComponent.area.height
            --compose label
            if (tComponent.componentType == "Label") then
               tComponent:setText(list.data[index][list.dataIndex[k]])
               self:composeLabel(tComponent, sState, list.listContent)
            --compose image
            elseif (tComponent.componentType == "Image") then
               tComponent:setFileName(list.data[index][list.dataIndex[k]])
               self:composeImage(tComponent, sState, list.listContent)
            end

            if (nWidth < 1) then
               tComponent.area.width = nWidth
            end
            if (nHeight < 1) then
               tComponent.area.height = nHeight
            end
         end

         nPos = nPos + 1
      end

      --unclip area
      list.listContent:attrClip(clipFocusedX, clipFocusedY, clipFocusedW, clipFocusedH)

      if ((list.nav.curColumn == list.nav.columnLimit and list.nav.curLine == list.nav.lineLimit) and not list.lastContent) then
         list.lastContent = canvas:new(list.listContent:attrSize())
         list.lastContent:attrColor(0, 0, 0, 0)
         list.lastContent:clear()
         list.lastContent:compose(0, 0, list.listContent)
      end

      tArea.left = list.area.left
      tArea.top = list.area.top
      tArea.width = list.area.width
      tArea.height = list.area.height
   else
      --set position
      list.children:setArea({
         left = nLeft,
         top = nTop,
         width = list.page.intervalLeft,
         height = list.page.intervalTop
      })


      local clipFocusedX, clipFocusedY, clipFocusedW, clipFocusedH = list.listContent:attrClip()

      list.listContent:attrClip(nLeft, nTop, list.page.intervalLeft, list.page.intervalTop)
      list.listContent:attrColor(0, 0, 0, 0)
      list.listContent:clear()

      local nPos = 1

      --draw elements
      local index = math.max(list.nav.curLine, list.nav.curColumn)
      for k = 1, #list.dataIndex do

         if (list.children.children[nPos]) then
            local sState = 'activated'

            local tComponent = list.children.children[nPos]
            local nWidth = tComponent.area.width
            local nHeight = tComponent.area.height
            --compose label
            if (tComponent.componentType == "Label") then
               tComponent:setText(list.data[index][list.dataIndex[k]])
               self:composeLabel(tComponent, sState, list.listContent)
            --compose image
            elseif (tComponent.componentType == "Image") then
               tComponent:setFileName(list.data[index][list.dataIndex[k]])
               self:composeImage(tComponent, sState, list.listContent)
            end

            if (nWidth < 1) then
               tComponent.area.width = nWidth
            end
            if (nHeight < 1) then
               tComponent.area.height = nHeight
            end
         end

         nPos = nPos + 1
      end

      --unclip area
      list.listContent:attrClip(clipFocusedX, clipFocusedY, clipFocusedW, clipFocusedH)

      tArea.left = list.area.left + nLeft
      tArea.top = list.area.top + nTop
      tArea.width = list.page.intervalLeft
      tArea.height = list.page.intervalTop
   end

   --clip page
   self.layers[list.z].content:attrClip(tArea.left, tArea.top, tArea.width, tArea.height)

   --clear
   self.layers[list.z].content:clear()

   --check focus
   if (bNeedFocus) then

      local nLeft = 0
      local nTop = 0

      if (list.listOrientation == list.orientation.vertical) then
         nTop = ((list.nav.curLine - list.page.linePosition) * list.page.intervalTop)
      else
         nLeft = ((list.nav.curColumn - list.page.columnPosition) * list.page.intervalLeft)
      end

      --clip area
      self.layers[list.z].content:attrClip(list.area.left + nLeft, list.area.top + nTop, list.page.intervalLeft, list.page.intervalTop)
      --compose focus
      self.layers[list.z].content:compose(list.area.left + nLeft, list.area.top + nTop, list.focusContent)
   end

   nLeft = list.area.left
   nTop = list.area.top

   self.layers[list.z].content:attrClip(tArea.left, tArea.top, tArea.width, tArea.height)
   self.layers[list.z].content:compose(nLeft, nTop, list.listContent)

   nLeft = list.area.left
   nTop = list.area.top

   --check scroll
   if (list.scrollContent and bUpdateMode) then
      nLeft = list.area.left + list.area.width - list.scroll.width
      nTop = list.area.top + math.floor((list.page.linePosition - 1) * (list.area.height / list.nav.lineLimit))

      local nWidth, nHeight = list.scrollContent:attrSize()

      --clip area
      self.layers[list.z].content:attrClip(nLeft, nTop, nWidth, nHeight)
      --compose scroll
      self.layers[list.z].content:compose(nLeft, nTop, list.scrollContent)
   end

   --unclip area
   self.layers[list.z].content:attrClip(clipX, clipY, clipW, clipH)

   tArea.left = tArea.left + self.area.left + self.layers[list.z].left
   tArea.top = tArea.top + self.area.top + self.layers[list.z].top

   --clear
   self.content:attrColor(unpack(self.color))
   self.content:clear()

   for i, v in pairs(self.layers) do
      self.content:compose(v.left, v.top, v.content)
   end

   if (bNeedFocus) then
      local bFlush = not (bAvoidFlush or false)
      self.parent:update(tArea, bFlush)
   else
      self.parent:update(tArea, false)
   end
end

function Window:updateListHUB(list, bNeedFocus, bUpdateMode, bAvoidFlush)
   local clipX, clipY, clipW, clipH = self.layers[list.z].content:attrClip()

   local tArea = {}

   local nTop = ((list.nav.curLine - list.page.linePosition) * list.page.intervalTop)
   local nLeft = ((list.nav.curColumn - list.page.columnPosition) * list.page.intervalLeft)

   --clip area
   if (bUpdateMode == list.updateMode.total) then
      if (list.cacheContent[list.currentPage]) then
         list.listContent:attrColor(0, 0, 0, 0)
         list.listContent:clear()
         list.listContent:compose(0, 0, list.cacheContent[list.currentPage])
      else
         self:composeListContentHUB(list)
      end

      tArea.left = list.area.left
      tArea.top = list.area.top
      tArea.width = list.area.width
      tArea.height = list.area.height
   else
      --set position
      list.children:setArea({
         left = nLeft,
         top = nTop,
         width = list.page.intervalLeft,
         height = list.page.intervalTop
      })

      local clipFocusedX, clipFocusedY, clipFocusedW, clipFocusedH = list.listContent:attrClip()

      list.listContent:attrClip(nLeft, nTop, list.page.intervalLeft, list.page.intervalTop)
      list.listContent:attrColor(0, 0, 0, 0)
      list.listContent:clear()

      local nPos = 1

      --draw elements
      --local index = math.max(list.nav.curLine, list.nav.curColumn)
      local index = ((list.nav.curLine - 1) * list.nav.columnLimit) + (list.nav.curColumn - 1) + 1
      for k = 1, #list.dataIndex do

         if (list.children.children[nPos]) then
            local sState = 'activated'

            local tComponent = list.children.children[nPos]
            local nWidth = tComponent.area.width
            local nHeight = tComponent.area.height
            --compose label
            if (tComponent.componentType == "Label") then
               tComponent:setText(list.data[index][list.dataIndex[k]])
               self:composeLabel(tComponent, sState, list.listContent)
            --compose image
            elseif (tComponent.componentType == "Image") then
               tComponent:setFileName(list.data[index][list.dataIndex[k]])
               self:composeImage(tComponent, sState, list.listContent)
            end

            if (nWidth < 1) then
               tComponent.area.width = nWidth
            end
            if (nHeight < 1) then
               tComponent.area.height = nHeight
            end
         end

         nPos = nPos + 1
      end

      --unclip area
      list.listContent:attrClip(clipFocusedX, clipFocusedY, clipFocusedW, clipFocusedH)

      tArea.left = list.area.left + nLeft
      tArea.top = list.area.top + nTop
      tArea.width = list.page.intervalLeft
      tArea.height = list.page.intervalTop
   end

   --clip page
   if (list.editMode) then
      self.layers[list.z].content:attrClip(tArea.left, tArea.top - (list.page.intervalTop * 0.5), tArea.width, tArea.height + (list.page.intervalTop * 0.5))
   else
      self.layers[list.z].content:attrClip(tArea.left, tArea.top, tArea.width, tArea.height)
   end

   --clear
   self.layers[list.z].content:clear()

   nLeft = list.area.left
   nTop = list.area.top

   self.layers[list.z].content:attrClip(tArea.left, tArea.top, tArea.width, tArea.height)
   self.layers[list.z].content:compose(nLeft, nTop, list.listContent)

   --check focus
   if (bNeedFocus and not list.editMode) then

      local nTop = ((list.nav.curLine - list.page.linePosition) * list.page.intervalTop)
      local nLeft = ((list.nav.curColumn - list.page.columnPosition) * list.page.intervalLeft)

      --clip area
      self.layers[list.z].content:attrClip(list.area.left + nLeft, list.area.top + nTop, list.page.intervalLeft, list.page.intervalTop)
      --compose focus
      self.layers[list.z].content:compose(list.area.left + nLeft, list.area.top + nTop, list.focusContent)
   end

   if (list.editMode and bNeedFocus) then
      local nTop = ((list.nav.curLine - list.page.linePosition) * list.page.intervalTop) - (list.page.intervalTop * 0.5)
      local nLeft = ((list.nav.curColumn - list.page.columnPosition) * list.page.intervalLeft)

      --clip area
      self.layers[list.z].content:attrClip(list.area.left + nLeft, list.area.top + nTop, list.page.intervalLeft, list.page.intervalTop)
      --compose focus
      self.layers[list.z].content:compose(list.area.left + nLeft, list.area.top + nTop, list.editContent)
   end

   nLeft = list.area.left
   nTop = list.area.top

   --check scroll
   if (list.scrollContent and bUpdateMode) then
      nLeft = list.area.left + list.area.width - list.scroll.width
      nTop = list.area.top + math.floor((list.page.linePosition - 1) * (list.area.height / list.nav.lineLimit))

      local nWidth, nHeight = list.scrollContent:attrSize()

      --clip area
      self.layers[list.z].content:attrClip(nLeft, nTop, nWidth, nHeight)
      --compose scroll
      self.layers[list.z].content:compose(nLeft, nTop, list.scrollContent)
   end

   --unclip area
   self.layers[list.z].content:attrClip(clipX, clipY, clipW, clipH)

   if (list.editMode) then
      tArea.left = tArea.left + self.area.left + self.layers[list.z].left
      tArea.top = tArea.top + self.area.top + self.layers[list.z].top - (list.page.intervalTop * 0.5)
      tArea.height = tArea.height + (list.page.intervalTop * 0.5)
   else
      tArea.left = tArea.left + self.area.left + self.layers[list.z].left
      tArea.top = tArea.top + self.area.top + self.layers[list.z].top
   end

   --clear
   self.content:attrColor(unpack(self.color))
   self.content:clear()

   for i, v in pairs(self.layers) do
      self.content:compose(v.left, v.top, v.content)
   end

   if (bNeedFocus) then
      local bFlush = not (bAvoidFlush or false)
      self.parent:update(tArea, bFlush)
   else
      self.parent:update(tArea, false)
   end
end

function Window:updateListEPG(list, bNeedFocus, bUpdateList, bAvoidFlush)
   local clipX, clipY, clipW, clipH = self.layers[list.z].content:attrClip()

   local tArea = {}

   --calculate left and top
   local nLeft = ((list.nav.curColumn - list.page.columnPosition[list.nav.curLine]) * list.page.intervalLeft)
   local nTop = ((list.nav.curLine - list.page.linePosition) * list.page.intervalTop)

   --clip area
   if (bUpdateList) then
      --update list page
      self:composeListContentEPG(list)

      tArea.left = list.area.left
      tArea.top = list.area.top
      tArea.width = list.area.width
      tArea.height = list.area.height
   else
      --update focused
      if (list.page.updateFocused) then
         --set position
         list.children:setArea({
            left = nLeft,
            top = nTop,
            width = list.page.intervalLeft,
            height = list.page.intervalTop
         })

         local clipFocusedX, clipFocusedY, clipFocusedW, clipFocusedH = list.listContent:attrClip()

         list.listContent:attrClip(nLeft, nTop, list.page.intervalLeft, list.page.intervalTop)
         list.listContent:attrColor(0, 0, 0, 0)
         list.listContent:clear()

         --draw background
         if (list.children.color[4] > 0) then
            list.listContent:attrColor(unpack(list.children.color))
            list.listContent:drawRect(
               'fill',
               nLeft,
               nTop,
               list.page.intervalLeft,
               list.page.intervalTop
            )
         end

         local nPos = 1

         --draw elements
         --[[
         for k, v in pairs(list.data[list.nav.curLine][list.nav.curColumn]) do

            if (type(v) == 'string' and list.children.children[nPos]) then
               local sState = 'activated'

               local tComponent = list.children.children[nPos]
               local nWidth = tComponent.area.width
               local nHeight = tComponent.area.height
               --compose label
               if (tComponent.componentType == "Label") then
                  tComponent:setText(v)
                  self:composeLabel(tComponent, sState, list.listContent)
               --compose image
               elseif (tComponent.componentType == "Image") then
                  tComponent:setFileName(v)
                  self:composeImage(tComponent, sState, list.listContent)
               end]]

         for k = 1, #list.dataIndex do
            local sState = 'activated'

            local tComponentBase = list.children.children[nPos]

            -- Here the magic begins
            local tComponent = _G[tComponentBase.componentType]:new()

            tComponent:setAnchors(tComponentBase.anchors)
            if (tComponent.componentType == "Label") then
               tComponent:setText(list.data[list.nav.curLine][list.nav.curColumn][list.dataIndex[k]])
            elseif (tComponent.componentType == "Image") then
               if (tComponentBase.fileName == '') then
                  tComponent:setFileName(list.data[list.nav.curColumn][list.nav.curColumn][list.dataIndex[k]])
               else
                  tComponent:setFileName(tComponentBase.fileName)
               end
            end

            if (tComponentBase.behavior) then
               tComponentBase.behavior(tComponent, list, list.data[list.nav.curLine][list.nav.curColumn][list.dataIndex[k]], list.nav.curLine, list.nav.curColumn, true)
            end

            local nWidth = tComponent.area.width
            local nHeight = tComponent.area.height

            if (tComponent.componentType == "Label") then
               self:composeLabel(tComponent, sState, list.listContent)
            elseif (tComponent.componentType == "Image") then
               self:composeImage(tComponent, sState, list.listContent)
            end


            if (nWidth < 1) then
               tComponent.area.width = nWidth
            end
            if (nHeight < 1) then
               tComponent.area.height = nHeight
            end

            nPos = nPos + 1
         end

         --unclip area
         list.listContent:attrClip(clipFocusedX, clipFocusedY, clipFocusedW, clipFocusedH)
      end

      tArea.left = list.area.left + nLeft
      tArea.top = list.area.top + nTop
      tArea.width = list.page.intervalLeft
      tArea.height = list.page.intervalTop
   end

   --clip page
   self.layers[list.z].content:attrClip(tArea.left, tArea.top, tArea.width, tArea.height)

   --clear
--   self.layers[list.z].content:attrColor(unpack(list.color))
   self.layers[list.z].content:clear()

   --check focus

   if (list.isFocusFront) then
      nLeft = list.area.left
      nTop = list.area.top

      self.layers[list.z].content:attrClip(tArea.left, tArea.top, tArea.width, tArea.height)
      self.layers[list.z].content:compose(nLeft, nTop, list.listContent)

      if (bNeedFocus) then

         if (list.dynamicFocus) then
            self:composeFocusContentEPG(list)
         end
         nLeft = ((list.nav.curColumn - list.page.columnPosition[list.nav.curLine]) * list.page.intervalLeft)
         nTop = ((list.nav.curLine - list.page.linePosition) * list.page.intervalTop)

         --clip area
         self.layers[list.z].content:attrClip(list.area.left + nLeft, list.area.top + nTop, list.page.intervalLeft, list.page.intervalTop)
         --compose focus
         self.layers[list.z].content:compose(list.area.left + nLeft, list.area.top + nTop, list.focusContent)
      end
   else
      if (bNeedFocus) then
         nLeft = ((list.nav.curColumn - list.page.columnPosition[list.nav.curLine]) * list.page.intervalLeft)
         nTop = ((list.nav.curLine - list.page.linePosition) * list.page.intervalTop)

         --clip area
         self.layers[list.z].content:attrClip(list.area.left + nLeft, list.area.top + nTop, list.page.intervalLeft, list.page.intervalTop)
         --compose focus
         self.layers[list.z].content:compose(list.area.left + nLeft, list.area.top + nTop, list.focusContent)
      end

      nLeft = list.area.left
      nTop = list.area.top

      self.layers[list.z].content:attrClip(tArea.left, tArea.top, tArea.width, tArea.height)
      self.layers[list.z].content:compose(nLeft, nTop, list.listContent)
   end

   nLeft = list.area.left
   nTop = list.area.top

   --check scroll
   if (list.scrollContent and bUpdateList) then
      nLeft = list.area.left + list.area.width - list.scroll.width
      nTop = list.area.top + math.floor((list.page.linePosition - 1) * (list.area.height / list.nav.lineLimit))

      local nWidth, nHeight = list.scrollContent:attrSize()

      --clip area
      self.layers[list.z].content:attrClip(nLeft, nTop, nWidth, nHeight)
      --compose scroll
      self.layers[list.z].content:compose(nLeft, nTop, list.scrollContent)
   end

   --unclip area
   self.layers[list.z].content:attrClip(clipX, clipY, clipW, clipH)

   tArea.left = tArea.left + self.area.left + self.layers[list.z].left
   tArea.top = tArea.top + self.area.top + self.layers[list.z].top

--   clipX, clipY, clipW, clipH = self.content:attrClip()

--   self.content:attrClip(tArea.left, tArea.top, tArea.width, tArea.height)

   --clear
   self.content:attrColor(unpack(self.color))
   self.content:clear()

   --unclip area
--   self.content:attrClip(clipX, clipY, clipW, clipH)

   for i, v in pairs(self.layers) do
      self.content:compose(v.left, v.top, v.content)
   end

   if (bNeedFocus) then
      local bFlush = not (bAvoidFlush or false)
      self.parent:update(tArea, bFlush)
   else
      self.parent:update(tArea, false)
   end
end

function Window:updateSignalMeter(signalMeter)
   local newHeight = math.floor((signalMeter.area.height / signalMeter.maxValue) * (100 - signalMeter.value))

   local clipX, clipY, clipW, clipH = self.layers[signalMeter.z].content:attrClip()
   self.layers[signalMeter.z].content:attrClip(signalMeter.area.left, signalMeter.area.top + newHeight, signalMeter.area.width, signalMeter.area.height - newHeight)
   self.layers[signalMeter.z].content:attrColor(0, 0, 0, 0)
   self.layers[signalMeter.z].content:clear()
   self.layers[signalMeter.z].content:compose(signalMeter.area.left, signalMeter.area.top, signalMeter.barContent)
   self.layers[signalMeter.z].content:attrClip(clipX, clipY, clipW, clipH)

   self.layers[signalMeter.z].content:attrClip(signalMeter.area.left, signalMeter.area.top, signalMeter.area.width, newHeight)
   self.layers[signalMeter.z].content:attrColor(0, 0, 0, 0)
   self.layers[signalMeter.z].content:clear()
   self.layers[signalMeter.z].content:compose(signalMeter.area.left, signalMeter.area.top, signalMeter.backContent)
   self.layers[signalMeter.z].content:attrClip(clipX, clipY, clipW, clipH)

   if (not signalMeter.noLabel) then
      self:composeLabel(signalMeter.label, nil, self.layers[signalMeter.z].content)
   end

   clipX, clipY, clipW, clipH = self.content:attrClip()
   --clip area
   self.content:attrClip(signalMeter.area.left, signalMeter.area.top, signalMeter.area.width, signalMeter.area.height)
   --clear
   self.content:attrColor(unpack(self.color))
   self.content:clear()

   --unclip area
   self.content:attrClip(clipX, clipY, clipW, clipH)

   for i, v in pairs(self.layers) do
      self.content:compose(v.left, v.top, v.content)
   end

   tArea = {}
   tArea.left = signalMeter.area.left + self.area.left
   tArea.top = signalMeter.area.top + self.area.top
   tArea.width = signalMeter.area.width
   tArea.height = signalMeter.area.height

   self.parent:update(tArea, true)
end

function Window:updateProgressBar(progressBar)
   local newWidth = math.floor((progressBar.area.width / progressBar.maxValue) * progressBar.value)

   local clipX, clipY, clipW, clipH = self.layers[progressBar.z].content:attrClip()
   self.layers[progressBar.z].content:attrClip(progressBar.area.left, progressBar.area.top, newWidth, progressBar.area.height)
   self.layers[progressBar.z].content:attrColor(0, 0, 0, 0)
   self.layers[progressBar.z].content:clear()
   self.layers[progressBar.z].content:compose(progressBar.area.left, progressBar.area.top, progressBar.barContent)
   self.layers[progressBar.z].content:attrClip(clipX, clipY, clipW, clipH)

   self.layers[progressBar.z].content:attrClip(progressBar.area.left + newWidth, progressBar.area.top, progressBar.area.width, progressBar.area.height)
   self.layers[progressBar.z].content:attrColor(0, 0, 0, 0)
   self.layers[progressBar.z].content:clear()
   self.layers[progressBar.z].content:compose(progressBar.area.left, progressBar.area.top, progressBar.backContent)
   self.layers[progressBar.z].content:attrClip(clipX, clipY, clipW, clipH)

   if (not progressBar.noLabel) then
      self:composeLabel(progressBar.label, nil, self.layers[progressBar.z].content)
   end

   clipX, clipY, clipW, clipH = self.content:attrClip()
   --clip area
   self.content:attrClip(progressBar.area.left, progressBar.area.top, progressBar.area.width, progressBar.area.height)
   --clear
   self.content:attrColor(unpack(self.color))
   self.content:clear()

   --unclip area
   self.content:attrClip(clipX, clipY, clipW, clipH)

   for i, v in pairs(self.layers) do
      self.content:compose(v.left, v.top, v.content)
   end

   tArea = {}
   tArea.left = progressBar.area.left + self.area.left
   tArea.top = progressBar.area.top + self.area.top
   tArea.width = progressBar.area.width
   tArea.height = progressBar.area.height

   self.parent:update(tArea, true)
end

function Window:updateIndexPage(indexPage)
   local clipX, clipY, clipW, clipH = self.layers[indexPage.z].content:attrClip()
   
   self.layers[indexPage.z].content:attrClip(indexPage.area.left, indexPage.area.top, indexPage.area.width, indexPage.area.height)
   self.layers[indexPage.z].content:attrColor(0, 0, 0, 0)
   self.layers[indexPage.z].content:clear()
   self.layers[indexPage.z].content:attrClip(clipX, clipY, clipW, clipH)

   self:composeIndexPage(indexPage)
   clipX, clipY, clipW, clipH = self.content:attrClip()
   --clip area
   self.content:attrClip(indexPage.area.left, indexPage.area.top, indexPage.area.width, indexPage.area.height)

   --clear
   self.content:attrColor(unpack(self.color))
   self.content:clear()

   --unclip area
   self.content:attrClip(clipX, clipY, clipW, clipH)
   
   for i, v in pairs(self.layers) do
      self.content:compose(v.left, v.top, v.content)
   end
   tArea = {}
   tArea.left = indexPage.area.left + self.area.left
   tArea.top = indexPage.area.top + self.area.top
   tArea.width = indexPage.area.width
   tArea.height = indexPage.area.height
   
   self.parent:update(tArea, true)
end

function Window:updateTextBox(textBox)
   
   local nWidth = 0
   if (textBox.scrollContent) then 
      nWidth = textBox.scrollContent:attrSize()
   end

   local clipX, clipY, clipW, clipH = self.layers[textBox.z].content:attrClip()
   self.layers[textBox.z].content:attrClip(textBox.area.left, textBox.area.top, textBox.area.width + 10 + nWidth, textBox.area.height)
   self.layers[textBox.z].content:attrColor(0, 0, 0, 0)
   self.layers[textBox.z].content:clear()
   --scrolling
   local nTop = textBox.area.top + (textBox.line * -textBox.lineSize) - 5 --@TODO change Label component

   self.layers[textBox.z].content:compose(textBox.area.left, nTop, textBox.textContent)
   self.layers[textBox.z].content:attrClip(clipX, clipY, clipW, clipH)

   --unclip area
   self.layers[textBox.z].content:attrClip(clipX, clipY, clipW, clipH)

   --clear
   self.content:attrColor(unpack(self.color))
   self.content:clear()

   --scroll bar
   if (textBox.scrollContent) then
      nLeft = textBox.area.left + textBox.area.width + 10
      nTop  = textBox.area.top + textBox.line *(textBox.area.height - math.floor(textBox.area.height/(textBox.label.area.height/textBox.area.height)) + textBox.scroll.width)/textBox.maxValue - (textBox.scroll.width*0.5)

      local nWidth, nHeight = textBox.scrollContent:attrSize()
      
      --clip area
      self.layers[textBox.z].content:attrClip(nLeft, nTop, nWidth, nHeight)
      --compose scroll
      self.layers[textBox.z].content:compose(nLeft, nTop, textBox.scrollContent)
   end
   
   for i, v in pairs(self.layers) do
      self.content:compose(v.left, v.top, v.content)
   end

   tArea = {}
   tArea.left = textBox.area.left + self.area.left
   tArea.top = textBox.area.top + self.area.top
   tArea.width = textBox.area.width + 10 + nWidth
   tArea.height = textBox.area.height

   self.parent:update(tArea, true)
end


function Window:reset()
   self.content = nil
   self.content = canvas:new(self.area.width, self.area.height)

   for i, v in pairs(self.layers) do
      v.content = nil
      v = nil
   end

   self.layers = {}

   collectgarbage()
end

function Window:dispose()
   self.content = nil
   for i, v in pairs(self.layers) do
      v.content = nil
      v = nil
   end
   collectgarbage()
end

return Window
